package com.hsh.maoduo.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.hsh.maoduo.anno.Alia;
import com.hsh.maoduo.anno.SheetInfo;
import com.hsh.maoduo.constant.SheetNameConstants;
import com.hsh.maoduo.constant.common.GlobalPathConstants;

import java.io.File;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author hsh
 * @DateTime 2023/09/09 14:56
 **/
public class HuToolExcelUtil extends ExcelUtil {

    /**
     * 读取Excel并转化为list
     * 需要指定返回时元素的类
     *
     * @param path  需要读取的Excel 的路径
     * @param clazz 指定的类，
     * @return list
     */
    public static <T> List<T> redaExcel(String path, Class<T> clazz) {
        if (!path.endsWith(GlobalPathConstants.XLSX_SUF) && !path.endsWith(GlobalPathConstants.XLS_SUF)) {
            path = path + GlobalPathConstants.XLSX_SUF;
        }
        File file = new File(path);
        List<T> list = new ArrayList<>();
        try (ExcelReader reader = ExcelUtil.getReader(file)) {
            reader.setHeaderAlias(getHeaderAlias(clazz, true));
            list = reader.readAll(clazz);
        }
        list = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
        System.out.println("↓↓↓↓↓↓↓↓↓↓\n读取文件：" + path + "\n数据条数：" + list.size() + "\n具体数据" + list);
        return list;
    }

    /**
     * 读取Excel并转化为list
     * 需要指定返回时元素的类
     *
     * @param names 需要读取的Excel 的集合
     * @param clazz 指定的类，
     * @return list
     */
    public static <T> List<T> redaExcels(String path, List<String> names, Class<T> clazz) {
        List<T> list = new ArrayList<>();
        for (String name : names) {
            list.addAll(redaExcel(path + name, clazz));
        }
        return list;
    }

    /**
     * 将list写入Excel中
     *
     * @param path 需要写入的Excel 的路径
     * @param list 写入的内容
     * @return
     */
    public static <T> void writeExcel(String path, List<T> list, Class<T> clazz) {
        if (!path.endsWith(GlobalPathConstants.XLSX_SUF) && !path.endsWith(GlobalPathConstants.XLS_SUF)) {
            path = path + GlobalPathConstants.XLSX_SUF;
        }
        Map<String, String> headerAlias = getHeaderAlias(clazz, false);
        SheetInfo anno = clazz.getAnnotation(SheetInfo.class);
        try (MyExcelWriter writer = MyExcelWriter.getWriter(new File(path), anno == null ? SheetNameConstants.DEFAULT_NOTE_SHEET_NAME : anno.name())) {
            writer.setHeaderAlias(headerAlias);
            // 写入并刷盘
            writer.write(list);

            list = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
            System.out.println("↓↓↓↓↓↓↓↓↓↓\n写入文件：" + path + "\n数据条数：" + list.size() + "\n具体数据" + list);
        }

    }

    /**
     * 删除文件
     *
     * @param path
     * @return
     */
    public static int deleteExcel(String path) {
        File file = new File(path);
        if (FileUtil.del(file)) {
            System.out.println("↓↓↓↓↓↓↓↓↓↓\n删除文件：" + path);
            return 1;
        }
        return 0;
    }

    /**
     * 删除文件
     *
     * @param path
     * @return
     */
    public static int deleteExcels(String path, List<String> names) {
        int flag = 0;
        for (String name : names) {
            boolean delFlag = FileUtil.del(new File(path + name));
            if (delFlag) {
                flag++;
            }
        }
        return flag;
    }


    /**
     * 获得一个类所有 有别名的 字段 和 别名
     *
     * @param clazz  类
     * @param isRead 每个键值对格式为 ("已有的","想改的")
     *               true 读取时 每个键值对格式为:(“别名”, “字段名”), 从excel中读取到“已有的(别名)”, 改为“想改的(字段名)”
     *               false 写入时 每个键值对格式为:(“字段名”, “别名”), 每个字段对应的“已有的(字段名)”, 改为“想改的(别名)”
     * @param <T>
     * @return
     */
    private static <T> Map<String, String> getHeaderAlias(Class<T> clazz, boolean isRead) {
        Map headerAlias = new LinkedHashMap<String, String>();
        // Hutool 获取字段集合的方法，无需try/catch
        List<Field> fields = Arrays.asList(ReflectUtil.getFields(clazz));
        if (fields.isEmpty()) {
            return headerAlias;
        }
        for (Field field : fields) {
            // 获得每个字段的 @ExcelAlias注解
            Alia anno = field.getAnnotation(Alia.class);
            if (anno == null || "".equals(anno.value())) {
                continue;
            }
            if (isRead) {
                // 读取时 每个键值对格式为:(“别名”, “字段名”)
                headerAlias.put(anno.value(), field.getName());
            } else {
                // 写入时 每个键值对格式为:(“字段名”, “别名”)
                headerAlias.put(field.getName(), anno.value());
            }
        }
        return headerAlias;
    }


}
